package net.slteam.base;

import com.fasterxml.jackson.annotation.JsonValue;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * ClassName: ISLEnum
 * Description:
 * date: 2019-10-08 19:15
 *
 * @author calm
 * @since JDK 1.8
 */
@SuppressWarnings("unused")
public interface ISLEnum{
    @JsonValue
    default Integer getCode() {
        return ((Enum)this).ordinal();
    }
    default String getDescription() {
        return ((Enum)this).name();
    }


    /**
     * 通过Code获取对应的枚举
     *
     * @param enumType 实际枚举类型
     * @param value    当前值
     * @param <T>      枚举类型并且实现 {@link ISLEnum} 接口
     * @return 枚举常量
     */
    static <T extends Enum<T> & ISLEnum> T valueOf(Class<T> enumType, Object value) {
        if (enumType == null || value == null) {
            return null;
        }

        T[] enumConstants = enumType.getEnumConstants();
        for (T enumConstant : enumConstants) {
            Object enumValue = enumConstant.getCode();
            if (Objects.equals(enumValue, value)
                    || Objects.equals(enumValue.toString(), value.toString())) {
                return enumConstant;
            }
        }

        return null;
    }


    /**
     * 通过Message获取对应的枚举
     *
     * @param enumType 实际枚举类型
     * @param description    当前值
     * @param <T>      枚举类型并且实现 {@link ISLEnum} 接口
     * @return 枚举常量
     */
    static <T extends Enum<T> & ISLEnum> T valueOfDescription(Class<T> enumType, String description) {
        if (enumType == null || description == null) {
            return null;
        }

        T[] enumConstants = enumType.getEnumConstants();
        for (T enumConstant : enumConstants) {
            Object enumValue = enumConstant.getDescription();
            if (Objects.equals(enumValue, description)
                    || Objects.equals(enumValue.toString(), description)) {
                return enumConstant;
            }
        }

        return null;
    }
    /**
     * java枚举类转List<Map>集合
     *
     * @param clazz
     * @return null-该class不是枚举类型  []-该枚举类型没有自定义字段  list-获取该枚举类型的List<Map>返回结果
     */
    static List<Map<String, Object>> toMapList(Class<?> clazz) {
        List<Map<String, Object>> resultList = null;
        // 判断是否是枚举类型
        if ("java.lang.Enum".equals(clazz.getSuperclass().getCanonicalName())) {
            resultList = new ArrayList<>();
            // 获取所有public方法
            Method[] methods = clazz.getMethods();
            List<Field> fieldList = new ArrayList<>();
            for (int i = 0; i < methods.length; i++) {
                String methodName = methods[i].getName();
                if (methodName.startsWith("get") && !"getDeclaringClass".equals(methodName) && !"getClass".equals(methodName)) { // 找到枚举类中的以get开头的(并且不是父类已定义的方法)所有方法
                    Field field = null;
                    try {
                        field = clazz.getDeclaredField(StringUtils.uncapitalize(methodName.substring(3))); // 通过方法名获取自定义字段
                    } catch (NoSuchFieldException | SecurityException e) {
                        e.printStackTrace();
                    }
                    if (field != null) { // 如果不为空则添加到fieldList集合中
                        fieldList.add(field);
                    }
                }
            }
            if (!fieldList.isEmpty()) { // 判断fieldList集合是否为空
                Map<String, Object> map = null;
                Enum<?>[] enums = (Enum[])clazz.getEnumConstants(); // 获取所有枚举
                for (int i = 0; i < enums.length; i++) {
                    map = new HashMap<>();
                    for (int l = 0, len = fieldList.size(); l < len; l++) {
                        Field field = fieldList.get(l);
                        field.setAccessible(true);
                        try {
                            map.put(field.getName(), field.get(enums[i])); // 向map集合添加字段名称 和 字段值
                        } catch (IllegalArgumentException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    resultList.add(map);// 将Map添加到集合中
                }
            }
        }
        return resultList;
    }

    static List<?> total(Class<? extends Enum> clazz) {
        return Arrays.asList(clazz.getEnumConstants());
    }
}
